RecyclerView实现拖动排序和滑动删除功能
RecyclerView 的拖动排序需要借助一下 ItemTouchHelper 这个类,ItemTouchHelper 类是 Google 提供的一个支持 RecyclerView 滑动和拖动的一个使用类,下面使用该类实现 RecyclerView 的滑动删除和拖动排序功能。首先大概介绍一下 ItemTouchHelper 的一个内部抽象类 Callback 。
ItemTouchHelper.Callback
该类是ItemTouchHelper类中的一个静态抽象类,作用主要是将ItemTouchHelper 与自己的应用联系在一起,让开发者通过 ViewHolder 控制每一个 View 的具体行为,接收用户的事件回调。该类里面有三个抽象方法:getMovementFlags、onMove、onSwiped。也是开发中经常要是用的。
getMovementFlags
该方法返回一个 Flags 表示Item的三种状态状态:idle(空闲)、 swiping(滑动)、dragging(拖动),根据 RecyclerView 不同的布局管理器,设置不同的滑动、拖动方向,一般使用 makeMovementFlags(int dragFlags, int swipeFlags)方法返回,dragFlags 表示拖动的方向,swipeFlags 表示滑动的方向。
1public abstract int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder);
onMove
当 ItemTouchHelper 拖动一个 Item 时该方法将会被回调,Item 将从旧的位置移动到新的位置,如果不拖动这个方法将从来不会调用,返回 true 表示 Item 已经被移动到新的位置。
1public abstract boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target);
onSwiped
当 Item 滑动的时候调用,如果不滑动该方法不会被调用,可通过 direction 做相应的判断执行某些操作。
1public abstract void onSwiped(ViewHolder viewHolder, int direction);
此外经常使用的方法有 onSelectedChanged、clearView等方法。
onSelectedChanged
当 item 由静止状态变为滑动或拖动状态时调用此方法,可通过 actionState 判断 Item 在哪种状态下执行某些操作,重写该方法时必须调用其父类的该方法。
1public void onSelectedChanged(ViewHolder viewHolder, int actionState) {
2 if (viewHolder != null) {
3 sUICallback.onSelected(viewHolder.itemView);
4 }
5}
clearView
当与用户交互结束或相关动画完成之后该方法被调用。
1public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) {
2 sUICallback.clearView(viewHolder.itemView);
3}
RecyclerView实现拖动排序
RecyclerView的拖动排序需要借助一个 android.support.v7.widget.helper.ItemTouchHelper 这个类来实现,拖动排序重点是在接口里面的 onMove(int fromPosition, int toPosition) 方法,其在 GridAdapter 中的具体实现参考如下:
1
2public void onMove(int fromPosition, int toPosition) {
3 if (fromPosition < toPosition) {
4 for (int i = fromPosition; i < toPosition; i++) {
5 Collections.swap(list, i, i + 1);
6 }
7 } else {
8 for (int i = fromPosition; i > toPosition; i--) {
9 Collections.swap(list, i, i - 1);
10 }
11 }
12 notifyItemMoved(fromPosition, toPosition);
13}
RecyclerView 实现侧滑删除
RecyclerView 的拖动排序需要借助一个 android.support.v7.widget.helper.ItemTouchHelper 这个类来实现,侧滑删除重点是在接口中的 onSwiped(int position),其在 GridAdapter 中的具体实现参考如下:
1
2 public void onSwiped(int position) {
3 Log.i("drag","onSwiped");
4 list.remove(position);
5 notifyItemRemoved(position);
6 }
参考代码
ItemTouchHelper.Callback 的实现类
1/**
2 * Created by jzman on 2017/5/17 0015.
3 */
4public class ItemTouchCallBack extends ItemTouchHelper.Callback {
5 private static final String TAG = "drag";
6 private OnItemTouchListener onItemTouchListener;
7
8 public void setOnItemTouchListener(OnItemTouchListener onItemTouchListener) {
9 this.onItemTouchListener = onItemTouchListener;
10 }
11
12 /**
13 * 根据 RecyclerView 不同的布局管理器,设置不同的滑动、拖动方向
14 * 该方法使用 makeMovementFlags(int dragFlags, int swipeFlags) 方法返回
15 * 参数: dragFlags:拖动的方向
16 * swipeFlags:滑动的方向
17 * @param recyclerView
18 * @param viewHolder
19 * @return
20 */
21
22 public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
23 Log.i(TAG,"getMovementFlags");
24 if (recyclerView.getLayoutManager() instanceof GridLayoutManager ||
25 recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager){
26 //此处不需要进行滑动操作,可设置为除4和8之外的整数,这里设为0
27 //不支持滑动
28 return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN |
29 ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT, 0 );
30 }else {
31 //如果是LinearLayoutManager则只能向上向下滑动,
32 //此处第二个参数设置支持向右滑动
33 return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN , ItemTouchHelper.RIGHT );
34 }
35 }
36
37 /**
38 * 当 ItemTouchHelper 拖动一个Item时该方法将会被回调,Item将从旧的位置移动到新的位置
39 * 如果不拖动这个方法将从来不会调用,返回true表示已经被移动到新的位置
40 * @param recyclerView
41 * @param viewHolder
42 * @param target
43 * @return
44 */
45
46 public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
47 Log.i(TAG,"onMove");
48 int fromPosition = viewHolder.getAdapterPosition();
49 int toPosition = target.getAdapterPosition();
50 onItemTouchListener.onMove(fromPosition,toPosition);
51 return true;
52 }
53
54 /**
55 * 当Item被滑动的时候被调用
56 * 如果你不滑动这个方法将不会被调用
57 * @param viewHolder
58 * @param direction
59 */
60
61 public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
62 Log.i(TAG,"onSwiped");
63 //此处是侧滑删除的主要代码
64 int position = viewHolder.getAdapterPosition();
65 onItemTouchListener.onSwiped(position);
66 }
67
68 /**
69 * 当Item被滑动、拖动的时候被调用
70 * @param viewHolder
71 * @param actionState
72 */
73
74 public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
75 Log.i(TAG,"onSelectedChanged");
76 //...
77 super.onSelectedChanged(viewHolder, actionState);
78 }
79
80 /**
81 * 当与用户交互结束或相关动画完成之后被调用
82 * @param recyclerView
83 * @param viewHolder
84 */
85
86 public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
87 Log.i(TAG,"clearView");
88 //...
89 super.clearView(recyclerView, viewHolder);
90 }
91
92 /**
93 * 移动交换数据的更新监听
94 */
95 public interface OnItemTouchListener {
96 //拖动Item时调用
97 void onMove(int fromPosition, int toPosition);
98 //滑动Item时调用
99 void onSwiped(int position);
100 }
101}
Adapter的实现
1/**
2 * Created by jzman on 2017/05/17 0009.
3 * RecycleView的Adapter
4 */
5public class GridAdapter extends RecyclerView.Adapter<GridAdapter.DataViewHolder> implements View.OnClickListener,ItemTouchCallBack.OnItemTouchListener {
6 private Context context;
7 private List<SimpleTitleGrid> list;
8
9 public GridAdapter(Context context, List<SimpleTitleGrid> list) {
10 this.context = context;
11 this.list = list;
12 }
13
14 /**
15 * 创建ViewHolder
16 * @param parent
17 * @param viewType
18 * @return
19 */
20
21 public DataViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
22 //加载item布局文件(每一个)
23 View view = LayoutInflater.from(context).inflate(R.layout.item,null);
24
25 //为View设置单击事件
26 view.setOnClickListener(this);
27 DataViewHolder viewHolder = new DataViewHolder(view);
28
29 //使用代码设置宽高(xml布局设置无效时)
30 view.setLayoutParams(new RecyclerView.LayoutParams(
31 ViewGroup.LayoutParams.MATCH_PARENT,
32 ViewGroup.LayoutParams.WRAP_CONTENT));
33 return viewHolder;
34 }
35
36 /**
37 * 绑定数据
38 * @param holder
39 * @param position
40 */
41
42 public void onBindViewHolder(DataViewHolder holder, int position) {
43 //设置每一个Item的高度
44 holder.textView.setText(list.get(position).getTitle());
45 }
46
47 /**
48 * 选项总数
49 * @return
50 */
51
52 public int getItemCount() {
53 return list.size();
54 }
55
56 /**
57 * 单击事件
58 * @param v
59 */
60
61 public void onClick(View v) {
62 if(onItemClickListener!=null){
63 int position = recyclerView.getChildAdapterPosition(v);
64 //程序执行到此,会执行该方法的具体实现
65 onItemClickListener.onItemClick(recyclerView,v,position,list.get(position));
66 }
67 }
68
69
70 public void onMove(int fromPosition, int toPosition) {
71 if (fromPosition < toPosition) {
72 for (int i = fromPosition; i < toPosition; i++) {
73 Collections.swap(list, i, i + 1);
74 }
75 } else {
76 for (int i = fromPosition; i > toPosition; i--) {
77 Collections.swap(list, i, i - 1);
78 }
79 }
80 notifyItemMoved(fromPosition, toPosition);
81 }
82
83
84 public void onSwiped(int position) {
85 Log.i("drag","onSwiped");
86 list.remove(position);
87 notifyItemRemoved(position);
88 }
89
90 /**
91 * RecycleView中针对ViewHolder来实现
92 */
93 public static class DataViewHolder extends RecyclerView.ViewHolder {
94 TextView textView;
95 public DataViewHolder(View itemView) {
96 super(itemView);
97 textView = (TextView) itemView.findViewById(R.id.tv_grid);
98 }
99 }
100 private RecyclerView recyclerView;
101 private OnItemClickListener onItemClickListener;
102 public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
103 this.onItemClickListener = onItemClickListener;
104 }
105 /**
106 * 设计recycleView选项单击事件的回调接口(给外面使用)
107 * 参考ListView选项单击事件方法
108 */
109 public interface OnItemClickListener{
110 //参数(父组件,点击的View,位置,这里可能是某个对象的id或对象/这里不需要)
111 void onItemClick(RecyclerView recyclerView, View view, int position, SimpleTitleGrid obj);
112 }
113 /**
114 * 将RecycleView附加到Adapter上
115 */
116
117 public void onAttachedToRecyclerView(RecyclerView recyclerView) {
118 super.onAttachedToRecyclerView(recyclerView);
119 this.recyclerView= recyclerView;
120 }
121 /**
122 * 将RecycleView从Adapter解除
123 */
124
125 public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
126 super.onDetachedFromRecyclerView(recyclerView);
127 this.recyclerView = null;
128 }
129}
MainActivity
1/**
2 * Created by jzman on 2017/05/17 0029.
3 * RecycleView的Adapter
4 */
5public class MainActivity extends AppCompatActivity implements GridAdapter.OnItemClickListener{
6 private RecyclerView rv_user;
7 private GridAdapter adapter;
8
9
10 protected void onCreate(Bundle savedInstanceState) {
11 super.onCreate(savedInstanceState);
12 setContentView(R.layout.activity_main);
13 initView();
14 }
15
16 private void initView() {
17 rv_user = (RecyclerView) findViewById(R.id.rv_user);
18 adapter = new GridAdapter(this, DataUtils.getUserGrids());
19
20 ItemTouchCallBack touchCallBack = new ItemTouchCallBack();
21 touchCallBack.setOnItemTouchListener(adapter);
22 ItemTouchHelper itemTouchHelper = new ItemTouchHelper(touchCallBack);
23
24 rv_user.setLayoutManager(new GridLayoutManager(this,3));
25// rv_user.setLayoutManager(new LinearLayoutManager(this));
26 rv_user.setAdapter(adapter);
27 itemTouchHelper.attachToRecyclerView(rv_user);
28
29 adapter.setOnItemClickListener(this);
30 }
31
32
33 public void onItemClick(RecyclerView recyclerView, View view, int position, SimpleTitleGrid obj) {
34 Toast.makeText(MainActivity.this, obj.getTitle(), Toast.LENGTH_SHORT).show();
35 }
36}